import { $ } from "execa";
import fs from "fs/promises";
import Handlebars from "handlebars";
import path from "path";
import replace from "replace-in-file";
import { rimraf } from "rimraf";
import { fileURLToPath } from "url";
import { setupGitIgnore } from "./gitIgnore";
import { setupCss } from "./setupCss";
import { shell } from "./shell";

const __dirname = path.dirname(fileURLToPath(import.meta.url));

export const setupCssNext = (folder: string) => {
  return setupCss(path.join(folder, "src/app/globals.css"));
};

type SetupNextjsOptions = {
  folder: string;
  exampleFolder: string;
  exampleName: string;
  exampleDescription: string;
  dependencies: string[];
  devDependencies: string[];
  nextjsVersion: string;
};

export const setupNextjs = async ({
  folder,
  exampleFolder,
  exampleName,
  exampleDescription,
  dependencies,
  devDependencies,
  nextjsVersion,
}: SetupNextjsOptions) => {
  await $`mkdir -p ${folder}`;

  await shell()`pnpm create next-app@${nextjsVersion} --ts --tailwind --eslint --app --src-dir --import-alias=@/* --use-npm ${folder}`;

  await replace({
    files: [path.join(folder, "package.json")],
    from: /"name": ".*",/,
    to: `"name": "${exampleName}",\n  "license": "MIT",`,
  });

  await shell({
    cwd: folder,
  })`npm install --save ${dependencies}`;

  await shell({
    cwd: folder,
  })`npm install --save-dev ${devDependencies}`;

  await fs.rm(path.join(folder, "package-lock.json"));

  await fs.rm(path.join(folder, "src/app/favicon.ico"));
  await rimraf(path.join(folder, "public"));

  const layoutFile = path.join(folder, "src/app/layout.tsx");

  await replace({
    files: [layoutFile],
    from: "Create Next App",
    to: exampleName,
  });

  await replace({
    files: [layoutFile],
    from: "Generated by create next app",
    to: exampleName,
  });

  const tailwindConfig = path.join(folder, "tailwind.config.ts");

  await replace({
    files: [tailwindConfig],
    from: "plugins: [],",
    to: "plugins: [typography],",
  });

  await replace({
    files: [tailwindConfig],
    from: `import type { Config } from "tailwindcss";`,
    to: `import type { Config } from "tailwindcss";\nimport typography from "@tailwindcss/typography";`,
  });

  const readMeTemplate = await fs.readFile(
    path.join(__dirname, "readme.md.hbs"),
    "utf8",
  );
  const template = Handlebars.compile(readMeTemplate);
  await fs.writeFile(
    path.join(folder, "readme.md"),
    template({ exampleFolder, exampleName, exampleDescription }),
  );
  await setupGitIgnore(folder);
  await setupCssNext(folder);
};
